#ifndef CLIENT_C
#define CLIENT_C


#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <pthread.h>
#include <curses.h>

#define TAILLEBUFFER 32

WINDOW *entete,*milieu, *saisie;
int ligne_affichage = 0;

/*==================================================================
       	 		 create_newwin
====================================================================*/
// Fonction pour creer une fenetre dans le terminal
// Prend en parametre la taille de la fenetre a creer 
// ainsi que la position ou placer le curseur dans cette fenetre
// Retourne un pointeur sur la fenetre cree
/*==================================================================*/
WINDOW *create_newwin(int height, int width, int starty, int startx)
{	WINDOW *local_win;

	local_win = newwin(height, width, starty, startx); //creation de la fenetre
	box(local_win, 0 , 0);		/* 0, 0 gives default characters 
										* for the vertical and horizontal
										* lines			*/
	wborder (local_win, '|', '|', '-', '-', '+', '+', '+', '+'); //affichage des bordures
	wrefresh(local_win);		/* Show that box 		*/

	return local_win;
}

/*==================================================================
       	 		 nettoyerw
====================================================================*/
// Fonction pour effacer le contenu d'une fenetre sauf ses bordures
// Prend en parametre un pointeur sur la fenetre a nettoyer
/*==================================================================*/
void nettoyerw (WINDOW *local_win)
{
	wclear (local_win);	//effacement du contenu de la fenetre
	wborder (local_win, '|', '|', '-', '-', '+', '+', '+', '+'); //affichage des bordures
	wrefresh (local_win); //rafraichissement de la fenetre
}

/*==================================================================
       	 		 waff_centre
====================================================================*/
// Fonction pour afficher du texte centre a une certaine position
// Prend en parametre un pointeur sur la fenetre ou ecrire
// ainsi que le texte a afficher et la position ou l'afficher
/*==================================================================*/
void waff_centre (WINDOW *local_win, char *txt, int x)
{
	mvwprintw (local_win, x, (COLS - strlen (txt))/2, "%s", txt);
	wrefresh (local_win);
}

/*==================================================================
       	 		 waff_normal
====================================================================*/
// Fonction pour afficher du texte et gerer les retour a la ligne
// Prend en parametre un pointeur sur la fenetre ou ecrire
// ainsi que le texte a afficher
/*==================================================================*/
void waff_normal (WINDOW *local_win, char *txt)
{
	ligne_affichage++;
	// On est arrivé en bas de la page
	if (ligne_affichage >= (LINES-6)*80/100) {
		nettoyerw(local_win);
		ligne_affichage = 1;
	}
	mvwprintw (local_win, ligne_affichage, 1, txt);
	wrefresh(local_win);
}

/*==================================================================
       	 		 init_entete
====================================================================*/
// Fonction pour afficher l'entete de notre programme
// Prend en parametre un pointeur sur la fenetre ou ecrire
/*==================================================================*/
void init_entete(WINDOW *entete)
{
	nettoyerw (entete);
	waff_centre (entete, "MASTERMIND", 1);
	waff_centre (entete, "Projet Réseau - IG 2010", 2);
	waff_centre (entete, "~ Radim BADSI - Célia BIGUZZI - Julien PARIS ~", 3);
	wrefresh (entete);
}

/*==================================================================
       	 		 waff_msg
====================================================================*/
// Fonction pour afficher du texte d'erreur / avertissement
// Prend en parametre un pointeur sur la fenetre ou ecrire
// ainsi que le texte a afficher
/*==================================================================*/

void waff_msg (WINDOW *local_win, char *txt)
{
	wattron(local_win, COLOR_PAIR(1));
	waff_centre (local_win, txt, (LINES-5)*80/100*90/100);
	wrefresh (local_win);
	wattroff(local_win, COLOR_PAIR(1));
}

/*==================================================================
       	 		 ecouter
====================================================================*/
// Fonction executee par le thread d'ecoute.
// Recoit et affiche les message du serveur
// Prend en parametre la socket connectee au serveur
/*==================================================================*/
void ecouter (void* sock) {
	char bufferRecep[TAILLEBUFFER];
	int recu = 0;
	
	int socket = *(int*)sock;

	while ((recu = recv(socket, bufferRecep, TAILLEBUFFER, 0)) > 0) {
	    bufferRecep[recu] = '\0';
	    waff_normal(milieu, bufferRecep);
	wmove(saisie, 1, 3);
	wrefresh(saisie);
	}	
}


int main(int argc, char *argv[])
{	
    int sock;
    struct sockaddr_in echoserver;
    char bufferEnv[TAILLEBUFFER];
    pthread_t ecouteServeur;
    unsigned int echolen;


	initscr();			/* Start curses mode 		*/
	start_color();			/* Start color			*/
	init_pair (1, COLOR_RED, COLOR_BLACK);

	refresh();
	entete = create_newwin(5, COLS, 0, 0);
	milieu = create_newwin((LINES-5)*80/100, COLS, 6, 0);
	saisie = create_newwin((LINES-5)*20/100, COLS, (LINES-5)*80/100+6, 0);
	
	init_entete(entete);

	    if (argc != 3)
    {
        waff_msg(milieu, "USAGE: TCPecho <server_ip> <port>");
        wrefresh(milieu);
        getch();
        endwin();
        exit(1);
    }
    /* Cree le socket */
    if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
    {
        waff_msg(milieu, "Probleme creation du socket.\n");
	wrefresh(milieu);
        getch();
        endwin();
        exit(-1);
    }
    /* Construire la structure sockaddr_in du serveur */
    memset(&echoserver, 0, sizeof(echoserver)); /* Initialiser la structure */
    echoserver.sin_family = AF_INET;    /* Internet/IP */
    echoserver.sin_addr.s_addr = inet_addr(argv[1]);    /* Adresse IP */
    echoserver.sin_port = htons(atoi(argv[2])); /* Port serveur */
    /* Establish connection */
    if (connect(sock, (struct sockaddr *) &echoserver, sizeof(echoserver)) < 0)
    {
        waff_msg(milieu, "Connexion au serveur impossible.\n");
        wrefresh(milieu);
        getch();
        endwin();
        exit(-1);
    }
  
 // Lancement du thread d'ecoute du serveur  
    pthread_create(&ecouteServeur, NULL, &ecouter, (void *) &sock);

// Boucle de saisie de texte a envoyer
while (1) { 
    mvwprintw(saisie, 1, 1, "> ");
    refresh();
    mvwscanw(saisie, 1, 3, "%s", bufferEnv);
    nettoyerw (saisie);
    bufferEnv[TAILLEBUFFER-1] = '\0',
    echolen = strlen(bufferEnv);
    if (send(sock, bufferEnv, echolen, 0) != echolen)
    {
        waff_msg(milieu, "Envoi impossible");
        wrefresh(milieu);
        getch();
        endwin();
        exit(-1);
    }
}
    close(sock);
	endwin();			/* End curses mode		  */
	return 0;
}

#endif;


